package com.objectproject.main.dao;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.objectproject.main.dao.iface.hierarchy.MyPropertyHierarchyDAO;
import com.objectproject.main.model.MyObject;
import com.objectproject.main.model.MyProperty;

@Repository
public class MyPropertyHierarchyDAOImpl implements MyPropertyHierarchyDAO {

	
	@Autowired
	MyObjectDAOImpl myObjectDAOImpl;

	@Autowired
	MyObjectHierarchyDAOImpl myObjectHierarchyDAOImpl;

	@Autowired
	MyPropertyDAOImpl myPropertyDAOImpl;

	// 일단 모든 구현은 프로퍼티와 오브젝트 계층 DAO로 해결한다 프로퍼티 계층 맵퍼가 구현되면 그때 이 클래스 구현을 맵퍼를 사용하는
	// 버전으로 바꾼다.

	// semantic : 의미상(valid 가 true 인 프로머피만 가져옴)

	@Override
	public ArrayList<MyProperty> semanticSelectSuperProperties(long objectId) {

		// 오버라이딩 메커니즘 구현안함

		ArrayList<MyObject> superObjects = myObjectHierarchyDAOImpl
				.selectSuperObjects(objectId);// 나중에 구현될때 semantic 형으로 선택되어야할 듯

		ArrayList<MyProperty> superProperties = new ArrayList<MyProperty>();

		MyObject currentObject;

		for (int i = 0; i < superObjects.size(); i++) {

			currentObject = superObjects.get(i);

			superProperties.addAll(myPropertyDAOImpl
					.semacticSelectMyProperties(currentObject));

		}

		return superProperties;
	}

	@Override
	public ArrayList<MyProperty> selectSuperProperties(long objectId) {
		// 오버라이딩 메커니즘 구현안함

		ArrayList<MyObject> superObjects = myObjectHierarchyDAOImpl
				.selectSuperObjects(objectId);// 나중에 구현될때 semantic 형으로 선택되어야할 듯

		ArrayList<MyProperty> superProperties = new ArrayList<MyProperty>();

		MyObject currentObject;

		for (int i = 0; i < superObjects.size(); i++) {

			currentObject = superObjects.get(i);

			superProperties.addAll(myPropertyDAOImpl
					.selectMyProperties(currentObject));

		}

		return superProperties;
	}

	@Override
	public ArrayList<MyProperty> semanticSelectAncestorProperties(long objectId) {
		// 오버라이딩 메커니즘 구현안함

		ArrayList<MyObject> ancestorObjects = myObjectHierarchyDAOImpl
				.selectAncestorObjects(objectId);// 나중에 구현될때 semantic 형으로 선택되어야할
													// 듯

		ArrayList<MyProperty> ancestorProperties = new ArrayList<MyProperty>();

		MyObject currentObject;

		for (int i = 0; i < ancestorObjects.size(); i++) {

			currentObject = ancestorObjects.get(i);

			ancestorProperties.addAll(myPropertyDAOImpl
					.semacticSelectMyProperties(currentObject));

		}

		return ancestorProperties;
	}

	@Override
	public ArrayList<MyProperty> selectAncestorProperties(long objectId) {
		// 오버라이딩 메커니즘 구현안함

		ArrayList<MyObject> ancestorObjects = myObjectHierarchyDAOImpl
				.selectAncestorObjects(objectId);// 나중에 구현될때 semantic 형으로 선택되어야할
													// 듯

		ArrayList<MyProperty> ancestorProperties = new ArrayList<MyProperty>();

		MyObject currentObject;

		for (int i = 0; i < ancestorObjects.size(); i++) {

			currentObject = ancestorObjects.get(i);

			ancestorProperties.addAll(myPropertyDAOImpl
					.selectMyProperties(currentObject));

		}

		return ancestorProperties;
	}

	@Override
	public ArrayList<MyProperty> semanticSelectFullProperties(long objectId) {
		// 오버라이딩 메커니즘 구현안함

		ArrayList<MyObject> ancestorObjects = myObjectHierarchyDAOImpl
				.selectAncestorObjects(objectId);// 나중에 구현될때 semantic 형으로 선택되어야할
													// 듯

		ArrayList<MyProperty> fullProperties = new ArrayList<MyProperty>();

		MyObject currentObject;

		for (int i = 0; i < ancestorObjects.size(); i++) {

			currentObject = ancestorObjects.get(i);

			fullProperties.addAll(myPropertyDAOImpl
					.semacticSelectMyProperties(currentObject));

		}

		fullProperties.addAll(myPropertyDAOImpl
				.semacticSelectMyProperties(myObjectDAOImpl
						.selectMyObjectById(objectId)));

		return fullProperties;
	}

	@Override
	public ArrayList<MyProperty> selectFullProperties(long objectId) {
		// 오버라이딩 메커니즘 구현안함

		ArrayList<MyObject> ancestorObjects = myObjectHierarchyDAOImpl
				.selectAncestorObjects(objectId);// 나중에 구현될때 semantic 형으로 선택되어야할
													// 듯

		ArrayList<MyProperty> fullProperties = new ArrayList<MyProperty>();

		MyObject currentObject;

		for (int i = 0; i < ancestorObjects.size(); i++) {

			currentObject = ancestorObjects.get(i);

			fullProperties.addAll(myPropertyDAOImpl
					.selectMyProperties(currentObject));

		}

		fullProperties.addAll(myPropertyDAOImpl
				.selectMyProperties(myObjectDAOImpl
						.selectMyObjectById(objectId)));

		return fullProperties;
	}

	@Override
	public ArrayList<MyProperty> semanticSelectFullPropertiesWithOverriding(
			long objectId) {

		ArrayList<MyObject> ancestorObjects = myObjectHierarchyDAOImpl
				.selectAncestorObjects(objectId);// 나중에 구현될때 semantic 형으로 선택되어야할
		// 듯

		ArrayList<MyObject> fullObjects = ancestorObjects;


		
		fullObjects.add(myObjectDAOImpl.selectMyObjectById(objectId));

		ArrayList<MyProperty> fullProperties = new ArrayList<MyProperty>();

		// 깊이 오름차순으로 객체리스트 정렬
		Collections.sort(fullObjects, new MyObjectDepthComparator());

		MyObject currentObject;

		ArrayList<MyProperty> currentProperties;

		MyProperty currentProperty;

		for (int i = 0; i < fullObjects.size(); i++) {

			currentObject = fullObjects.get(i);

			currentProperties = myPropertyDAOImpl
					.semacticSelectMyProperties(currentObject);

			// overriding mechanism
			for (int j = 0; j < currentProperties.size(); j++) {
				currentProperty = currentProperties.get(j);
				if (fullProperties.contains(currentProperty)) {// 중요한 대목,
																// equals의 구현이
																// 바뀌면 오작동할것이다.
																// property_id만
																// 비교!
					fullProperties.remove(currentProperty);
				}
			}
			// end of overriding mechanism

			fullProperties.addAll(currentProperties);

		}
		return fullProperties;
	}

	@Override
	public ArrayList<MyProperty> selectFullPropertiesWithOverriding(
			long objectId) {
		ArrayList<MyObject> ancestorObjects = myObjectHierarchyDAOImpl
				.selectAncestorObjects(objectId);// 나중에 구현될때 semantic 형으로 선택되어야할
		// 듯

		ArrayList<MyObject> fullObjects = ancestorObjects;

		fullObjects.add(myObjectDAOImpl.selectMyObjectById(objectId));

		ArrayList<MyProperty> fullProperties = new ArrayList<MyProperty>();

		// 깊이 오름차순으로 객체리스트 정렬
		Collections.sort(fullObjects, new MyObjectDepthComparator());

		MyObject currentObject;

		ArrayList<MyProperty> currentProperties;

		MyProperty currentProperty;

		for (int i = 0; i < fullObjects.size(); i++) {

			currentObject = fullObjects.get(i);

			currentProperties = myPropertyDAOImpl
					.selectMyProperties(currentObject);

			// overriding mechanism
			for (int j = 0; j < currentProperties.size(); j++) {
				currentProperty = currentProperties.get(j);
				if (fullProperties.contains(currentProperty)) {// 중요한 대목,
																// equals의 구현이
																// 바뀌면 오작동할것이다.
																// property_id만
																// 비교!
					fullProperties.remove(currentProperty);
				}
			}
			// end of overriding mechanism

			fullProperties.addAll(currentProperties);

		}
		return fullProperties;
	}

	private class MyObjectDepthComparator implements Comparator<MyObject> {

		@Override
		public int compare(MyObject o1, MyObject o2) {
			if (o1.getDepth() > o2.getDepth()) {
				return 1;
			} else if (o1.getDepth() < o2.getDepth()) {
				return -1;
			}
			return 0;
		}

	}

}
